package HashMap.Nodo.Subclases;

import HashMap.Nodo.Categoria;
import HashMap.Nodo.Clase;
import HashMap.Nodo.Nodo;
import HashMap.Nodo.TipoBasicoDeDatos;

public class VectorPropio implements Nodo {

    private String nombre;
    private TipoBasicoDeDatos tipoBasico;
    private Categoria categoria;
    private Clase clase;
    private int numeroDeParametros;
    private int posicionDeParametro;
    private int dimension;
    private int numeroDeFilas;
    private int numeroDeColumnas;
    private String operacion;

    public VectorPropio(String nombre, TipoBasicoDeDatos tipoBasico, Categoria categoria, int dimension, String operacion) {
        this.nombre = nombre;
        this.tipoBasico = tipoBasico;
        this.categoria = categoria;
        if (dimension == 1 || dimension == 2) {
            this.dimension = dimension;
        } else {
            throw new RuntimeException("La dimension no puede ser distinto de 1 o 2");
        }
        this.clase = Clase.VECTOR;
        this.operacion = operacion;
    }

    @Override
    public Clase getClase() {
        return this.clase;
    }

    @Override
    public String getNombre() {
        if (nombre != null) {
            return this.nombre;
        } else {
            return "";
        }
    }

    @Override
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    @Override
    public void clearNombre() {
        this.nombre = null;
    }

    @Override
    public int getNumeroDeParametros() {
        if (this.categoria == Categoria.FUNCION) {
            return this.numeroDeParametros;
        } else {
            throw new RuntimeException("Error de tipos incompatibles. Debería ser Funcion y "
                    + " es un " + categoria);
        }
    }

    @Override
    public void setNumeroDeParametros(int numeroDeParametros) {
        if (this.categoria == Categoria.FUNCION) {
            this.numeroDeParametros = numeroDeParametros;
        } else {
            throw new RuntimeException("Error de tipos incompatibles. Debería ser Funcion y "
                    + " es un " + categoria);
        }
    }

    @Override
    public int getPosicionDeParametro() {
        if (this.categoria == Categoria.PARAMETRO) {
            return this.posicionDeParametro;
        } else {
            throw new RuntimeException("Error. No es un parámetro."
                    + " Es un " + categoria);
        }
    }

    @Override
    public void setPosicionDeParametro(int posicionDeParametro) {
        if (this.categoria == Categoria.PARAMETRO) {
            this.posicionDeParametro = posicionDeParametro;
        } else {
            throw new RuntimeException("Error. No es un parámetro."
                    + " Es un " + categoria);
        }
    }

    @Override
    public TipoBasicoDeDatos getTipoBasicoDeDatos() {
        return this.tipoBasico;
    }

    @Override
    public int getNivelDeIndireccion() {
        return -1;
    }

    @Override
    public void setNivelDeIndireccion(int nivelDeIndireccion) {
        throw new UnsupportedOperationException("Los vectores no soportan indirección");
    }

    @Override
    public Categoria getCategoria() {
        return this.categoria;
    }

    public int getNumeroDeFilas() {
        return numeroDeFilas;
    }

    public void setNumeroDeFilas(int numeroDeFilas) {
        if (numeroDeFilas >= 1 && numeroDeFilas <= 64) {
            this.numeroDeFilas = numeroDeFilas;
        } else {
            throw new IllegalArgumentException("número de filas fuera de rango [1-64]");
        }
    }

    public int getNumeroDeColumnas() {
        return numeroDeColumnas;
    }

    public void setNumeroDeColumnas(int numeroDeColumnas) {
        if (this.dimension == 2 && numeroDeColumnas >= 1 && numeroDeColumnas <= 64) {
            this.numeroDeColumnas = numeroDeColumnas;
        } else {
            throw new IllegalArgumentException("número de filas fuera de rango [1-64]"
                    + " y la dimensión de 2");
        }
    }

    public int getDimension() {
        return dimension;
    }

    @Override
    public String generarCodigoNASM() {
        if (dimension == 1) {
            return nombre + " resd " + numeroDeFilas;
        } else {
            return nombre + " resd " + numeroDeFilas * numeroDeColumnas;
        }//tamaño de variable de 4 bytes + filas y columnas(si vector es 2D)
    }

    @Override
    public Nodo copiarNodo() {
        VectorPropio vector = new VectorPropio(nombre, tipoBasico, categoria, dimension, operacion);
        vector.setNumeroDeFilas(numeroDeFilas);
        if (this.categoria == Categoria.FUNCION) {
            vector.setNumeroDeParametros(numeroDeParametros);
        }
        if (this.dimension == 2 && numeroDeColumnas >= 1 && numeroDeColumnas <= 64) {
            vector.setNumeroDeColumnas(numeroDeColumnas);
        }
        if (this.categoria == Categoria.PARAMETRO) {
            vector.setPosicionDeParametro(posicionDeParametro);
        }
        return vector;
    }

    @Override
    public void setOperacion(String operacion) {
        this.operacion = operacion;
    }

    @Override
    public String getOperacion() {
        return this.operacion;
    }
}
